package com.dongzili.easyes.common.aspect;

import cn.hutool.json.JSONUtil;
import com.dongzili.easyes.common.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
@Slf4j
public class ApiAccessLogAspect {


    // 拦截所有控制器的public方法
    @Pointcut("execution(public * com.dongzili.easyes.*.controller..*.*(..))")
    public void apiPointcut() {}

    @Around("apiPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 1. 前置处理：记录请求开始时间和参数
        long startTime = System.currentTimeMillis();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return joinPoint.proceed(); // 非HTTP请求直接放行
        }
        HttpServletRequest request = attributes.getRequest();
        String traceId = TraceIdUtils.getTraceId();
        Object result = null;
        try {
            result = joinPoint.proceed();
            return result;
        } finally {
            if (result instanceof R){
                R<?> r = (R<?>) result;
                r.setTimes(System.currentTimeMillis() - startTime);
                r.setTraceId(traceId);
            }
        }
    }


    // 工具方法：获取客户端IP
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    // 工具方法：获取请求参数
//    private String getRequestParams(ProceedingJoinPoint joinPoint, HttpServletRequest request) {
//        // 实现逻辑：根据请求方法（GET/POST）获取参数并转为JSON
//        // 简化示例，实际需处理复杂参数（如文件上传可忽略）
//        String queryString = null;
//        if (request != null) {
//            queryString = JSONUtil.toJsonStr(request.getQueryString());
//        }
//        if (queryString == null) {
//            if (request != null) {
//                queryString = JSONUtil.toJsonStr(request.getParameterMap());
//            }
//        }
//        return queryString;
//    }

    /**
     * 获取请求参数（支持多种参数类型）
     */
    private Map<String, Object> getRequestParams(JoinPoint joinPoint) {
        Map<String, Object> paramMap = new HashMap<>();

        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Parameter[] parameters = method.getParameters();
        Object[] args = joinPoint.getArgs();

        // 遍历参数，处理不同类型的参数
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            Object arg = args[i];

            // 处理@RequestParam注解的参数
            RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
            if (requestParam != null) {
                String paramName = requestParam.value();
                if (paramName.isEmpty()) {
                    paramName = parameter.getName();
                }
                paramMap.put(paramName, arg);
                continue;
            }

            // 处理@RequestBody注解的参数（JSON对象）
            RequestBody requestBody = parameter.getAnnotation(RequestBody.class);
            if (requestBody != null && arg != null) {
                // 将JSON对象转换为Map
                try {
//                    ObjectMapper objectMapper = new ObjectMapper();
//                    String argStr = JSONUtil.parseObj(arg);// objectMapper.writeValueAsString(arg);
                    paramMap.put("request_body", JSONUtil.parseObj(arg));

                } catch (Exception e) {
                    // 转换失败时直接放入对象
                    paramMap.put(parameter.getName(), arg);
                }
                continue;
            }

            // 处理路径参数（如@PathVariable，需要结合URL解析，这里简化处理）
            // 复杂场景建议使用RequestContextHolder获取完整请求信息解析

            // 处理普通参数（非注解参数）
            paramMap.put(parameter.getName(), arg);
        }

        return paramMap;
    }
}